package com.hjx.movie.core.system.service.admin.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hjx.movie.common.utils.ResultType;
import com.hjx.movie.common.utils.exceptions.CustomException;
import com.hjx.movie.core.system.service.admin.IRoleService;
import com.hjx.movie.core.system.service.admin.IUserRoleService;
import com.hjx.movie.core.util.cache.CacheKey;
import com.hjx.movie.core.util.cache.CacheUtil;
import com.hjx.movie.persistence.system.mapper.IvyUserRoleMapper;
import com.hjx.movie.persistence.system.model.IvyRole;
import com.hjx.movie.persistence.system.model.IvyUserRole;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>Title:</p>
 * <p>Description:</p>
 *
 * @author hjx
 * @date 2021/1/27 - 17:23
 */
@Slf4j
@Service
@Transactional
@CacheConfig(cacheNames = "IvyMovie:SpringCache:UserRoleCache",keyGenerator = "cacheKeyGenerator")
public class UserRoleService extends ServiceImpl<IvyUserRoleMapper, IvyUserRole> implements IUserRoleService {

    @Resource
    private CacheUtil<IvyUserRole> cacheUtil;
    public static final String USER_ROLE_KEY = CacheUtil.cacheNameFormat(CacheKey.SYSTEM.getName(),CacheKey.USER_ROLE.getName());
    public static final String USER_ROLE_CACHE_DATA = CacheUtil.cacheNameFormat(CacheKey.SYSTEM.getName(),CacheKey.USER_ROLE.getName(),CacheKey.PRE_SAVE_USER_ROLE.getName());

    @Resource
    IRoleService roleService;

    @Cacheable(unless = "#result==null")
    @Override
    public Set<Long> findCheckedRoleIds(Long userId) {
        List<IvyUserRole> cacheList = cacheUtil.getCacheList(USER_ROLE_CACHE_DATA);
        return cacheList.stream().filter(item->item.getUserId().equals(userId))
                .map(IvyUserRole::getRoleId).collect(Collectors.toSet());
    }

    @Cacheable(unless = "#result==null")
    @Override
    public Map<String,Object> findCheckedAndRoleIds(Long userId) {
        Map<String,Object> map = new HashMap<>();
        List<IvyRole> allRole = roleService.findAllRole();
        map.put("roles",allRole);
        map.put("checkedRoleIds",findCheckedRoleIds(userId));
        return map;
    }

    @Caching(evict = {
            @CacheEvict(value="IvyMovie:SpringCache:AuthCache",
                    key="'com.hjx.movie.core.security.service.impl.AuthService:findRoleByUserId:'+#userId",
                    beforeInvocation = true),
            @CacheEvict(value = "IvyMovie:SpringCache:UserRoleCache",allEntries = true,beforeInvocation = true)
    })
    @Override
    public boolean addOrDeleteUserRole(Long userId, Set<Long> roleIds) {
        Set<Long> rawRoles = findCheckedRoleIds(userId);
        addUserRole(userId,roleIds,rawRoles);
        deleteUserRole(userId,roleIds,rawRoles);
        return true;
    }

    public void addUserRole(Long userId,Set<Long> roleIds,Set<Long> rawRoleIds){
        Set<Long> copyRoleIds = new HashSet<>(roleIds);
        Set<Long> copyRawRoleIds = new HashSet<>(rawRoleIds);
        copyRoleIds.removeAll(copyRawRoleIds);
        if (copyRoleIds.isEmpty()){
            return;
        }
        log.debug("用户新增角色===>用户标识:{},新增角色标识:{}",userId,copyRoleIds);
        List<IvyUserRole> userRoles = copyRoleIds.stream().map(id->{
            IvyUserRole userRole = new IvyUserRole();
            userRole.setUserId(userId);
            userRole.setRoleId(id);
            userRole.setStatus(true);
            return userRole;
        }).collect(Collectors.toList());
        if (saveBatch(userRoles)){
            for (IvyUserRole userRole:userRoles){
                cacheUtil.getOpsForHash().put(USER_ROLE_CACHE_DATA,userRole.getUserRoleId().toString(),userRole);
            }
        }else {
            log.error("保存用户的角色失败");
            throw new CustomException(ResultType.USER_INPUT_ERROR,"保存用户的角色失败");
        }
    }
    public void deleteUserRole(Long userId,Set<Long> roleIds,Set<Long> rawRoleIds){
        Set<Long> copyRoleIds = new HashSet<>(roleIds);
        Set<Long> copyRawRoleIds = new HashSet<>(rawRoleIds);
        copyRawRoleIds.removeAll(copyRoleIds);
        if (copyRawRoleIds.isEmpty()){
            return;
        }
        log.debug("删除用户的角色===>用户为:{},要删除的角色标识为:{}",userId,copyRawRoleIds);
        List<IvyUserRole> userRoles = cacheUtil.getCacheList(USER_ROLE_CACHE_DATA);
        List<String> removeUserRoleIds = userRoles.stream()
                .filter(item->item.getUserId().equals(userId)&&copyRawRoleIds.contains(item.getRoleId()))
                .map(item->item.getUserRoleId().toString()).collect(Collectors.toList());
        if (removeByIds(removeUserRoleIds)){
            cacheUtil.getOpsForHash().delete(USER_ROLE_CACHE_DATA,removeUserRoleIds.toArray());
        }else {
            throw new CustomException(ResultType.USER_INPUT_ERROR,"删除用户的角色失败");
        }

    }


}
